cmake_minimum_required(VERSION 3.20)
## 定义是否启用 CUDA
option(my_USE_CUDA "Enable CUDA support" ON)
set(my_LANG_LIST)
if(my_USE_CUDA)
    set(my_LANG_LIST CUDA)
    # message(STATUS "[my] CMAKE_CUDA_COMPILER_FORCED -> TRUE")
    # set(CMAKE_CUDA_COMPILER "C:/MyProgram/cuda/bin/nvcc.exe")
    # set(CMAKE_CUDA_COMPILER_FORCED TRUE)
endif()
project(myop3 LANGUAGES CXX ${my_LANG_LIST})

include(0configs.cmake)

##0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 projects targets

##=========================== Python module
set(my_LIB ${PROJECT_NAME})
Python_add_library(${my_LIB}
    csrc/myop3.cpp
)
my_config_msvc_relwithdebinfo(${my_LIB})
my_config_export_header(${my_LIB} ${my_EXPORTS_DIR} FALSE)
## 添加 public 头文件
target_sources(${my_LIB}
    PUBLIC FILE_SET HEADERS TYPE HEADERS
    BASE_DIRS
        "${CMAKE_CURRENT_SOURCE_DIR}/csrc" "${my_EXPORTS_DIR}"
    FILES
        csrc/myop3.h
        "${my_EXPORTS_DIR}/myop3_export.h"
)
## preprocessor
target_compile_definitions(${my_LIB}
    PRIVATE Py_LIMITED_API=0x03090000
)
## include directories
target_include_directories(${my_LIB}
    PRIVATE
        ${CMAKE_CURRENT_SOURCE_DIR}
        ${my_EXPORTS_DIR}
)
## 可能需要添加 $env:PYTHONHOME/libs 目录
target_link_directories(${my_LIB}
    PUBLIC ${Python_LIBRARY_DIRS}
)
## 链接依赖库;
target_link_libraries(${my_LIB}
    PRIVATE torch
)
##
set_target_properties(${my_LIB} PROPERTIES
    INTERPROCEDURAL_OPTIMIZATION ON
    # CXX_VISIBILITY_PRESET hidden
    # VISIBILITY_INLINES_HIDDEN ON
)
##=========================== 设置模块的输出目录为二进制目录
if(FALSE)
    set_target_properties(${my_LIB} PROPERTIES
        LIBRARY_OUTPUT_DIRECTORY "${my_PATH_BIN}"
        RUNTIME_OUTPUT_DIRECTORY "${my_PATH_BIN}"
    )
endif()
message(STATUS "Successfully configured Python binding module: ${my_LIB}")

##============================= 为Visual Studio生成文件夹结构（如果适用）
if(MSVC)
    set_target_properties(${my_LIB} PROPERTIES FOLDER "dose_stat")
endif()

##============================= 添加编译选项以提高代码质量
if(FALSE AND MSVC)
    target_compile_options(${my_LIB} PRIVATE /W4 /WX)
endif()
if(LINUX)
    # target_compile_options(${my_LIB} PRIVATE -Wall -Wextra -Wpedantic -Werror)
    target_compile_options(${my_LIB} PRIVATE -Wall -Wextra -Wpedantic)
endif()

##0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 install settings
#xxxxxxxxxxxxxxxxxxxxxxxcxxx python 模块目录
set(my_INST_PYD_DIR "${my_ROOT_DIR}/src/myop3/lib")
set(my_INST_INC_DIR "${my_ROOT_DIR}/src/myop3/include")

#xxxxxxxxxxxxxxxxxxxxxxxcxxx 打包系统库
set(CMAKE_INSTALL_UCRT_LIBRARIES TRUE)   # Win10 以前必备; 安装 Windows 通用 CRT（UCRT）库
set(CMAKE_INSTALL_DEBUG_LIBRARIES FALSE) # Debug 版 runtime
set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_SKIP TRUE)  # 禁止自动 install, 可以手动定制
include(InstallRequiredSystemLibraries)
message(STATUS "[my] System runtime detected:")
if(FALSE)
    foreach(f ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS})
        message("    ${f}")
    endforeach()
endif()

install(TARGETS ${my_LIB}
    FILE_SET HEADERS DESTINATION "${my_INST_INC_DIR}"
    RUNTIME DESTINATION "${my_INST_PYD_DIR}"
    LIBRARY DESTINATION "${my_INST_PYD_DIR}"
    ARCHIVE DESTINATION "${my_INST_PYD_DIR}"
)

##xxxxxxxxxxxxxxxxxxxxxxxxxxx windows, 打包 c10, c10_cuda, torch_cpu, torch_cuda 等 dll
if(WIN32 AND FALSE)
    install(FILES "$<TARGET_RUNTIME_DLLS:${my_LIB}>"
        DESTINATION "${my_INST_PYD_DIR}"
    )
endif()

##xxxxxxxxxxxxxxxxxxxxxxxxxxx conan runtime dlls
if(WIN32 AND EXISTS "${my_CONAN_RUNTIME_DIR}")
    install(DIRECTORY "${my_CONAN_RUNTIME_DIR}"
        DESTINATION "${my_INST_PYD_DIR}"
        USE_SOURCE_PERMISSIONS
        ## 单独组件名, 可以使用 cmake --install . --component conan_runtime 单独装
        # COMPONENT conan_runtime
    )
endif()

#xxxxxxxxxxxxxxxxxxxxxxxxxxx 3rd lib header-only 库
if(WIN32 AND EXISTS "${my_THIRD_PARTY_HXX}")
    install(DIRECTORY "${my_THIRD_PARTY_HXX}"
        DESTINATION include
        USE_SOURCE_PERMISSIONS
    )
endif()


##0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 executable 程序
## 安装主程序
# install(TARGETS ${MYEXE} DESTINATION "${my_INST_EXE_DIR}")
# install(TARGETS ${my_EXE} RUNTIME DESTINATION "${my_INST_EXE_DIR}")

##xxxxxxxxxxxxxxxxxxxxxxxxxxx cpack 设置
if(my_EXE)
    set(CPACK_GENERATOR "ZIP")       # Windows 用 ZIP/NSIS, macOS 用 DragNDrop
    set(CPACK_PACKAGE_NAME ${my_EXE})
    set(CPACK_PACKAGE_VERSION ${my_EXE_VERSION})
    set(CPACK_PACKAGE_DIRECTORY "${CMAKE_SOURCE_DIR}/dist_package")
    include(CPack)
endif()